#include "StepByStep.h"

#ifdef DFS
Bool ExpandOneActKnowledge(int Height, ActKnowledge *ActK)
{
  PredKnowledge *PC;
  Bool           Ok, UComplete;
  int            HPc, Acts;

  for (PC = ActK->PC; PC != NULL; PC = PC->next) {
    if (IsEqual(PC->PredNo)) continue;

    PC->UComplete = FALSE;

    Ok = FindOneCurrentFact(PC, &Ok);
//PrintPredication(12, PC); fprintf(Output, "\n");
    if (PC->Type == NOT) Ok = !Ok;
    if (Ok) {
       PC->SAT = PC->Fact = TRUE;
       continue;
    }

    if (FindOneNoConfirmFact(PC, NULL)) {
       PC->SAT = TRUE;  PC->Fact = FALSE;
       continue;
    }

    if (Height == 0) { // PRUNING
       PC->Height = PC->Acts = MAX_HEIGHT;
       PC->UComplete = TRUE;
       continue;
    }

    if (IsClass(PC->PredNo, STATIC)) return FALSE;

    // if (!ExistPCLoop(PC))
    GenerateKnowledgeTreeByDFS(Height, PC);

    if (PC->Act == NULL) return FALSE;
  }

  Ok = TRUE;
  Acts = HPc = 0;  UComplete = FALSE;
  for (PC = ActK->PC; Ok && PC != NULL; PC = PC->next) {
    UComplete = UComplete || PC->UComplete;

    if (HPc < PC->Height) HPc = PC->Height;
    Acts += PC->Acts;

    Ok = (PC->SAT || PC->Act != NULL || PC->UComplete);
  }

  if (Ok) {
     PredKnowledge *PC12, *PC21, *PC22;

     ActK->Acts = Acts;
     ActK->Height = HPc;  ActK->UComplete = UComplete;

//fprintf(Output, "\nBBBBB"); PrintActKnowledge(12, ActK); fprintf(Output, "\n");
     PC22 = NULL;        // (PC21, PC22): list of fact PC
     PC12 = NULL;        // Previous of PC
     for (PC = ActK->PC; PC != NULL; PC = PC->next)
       if (PC->Act != NULL) PC12 = PC;
       else {
              if (PC12 == NULL) ActK->PC = PC->next;
              else PC12->next = PC->next;

              if (PC22 == NULL) PC21 = PC;
              else PC22->next = PC;
              PC22 = PC;
       }

     if (PC22 != NULL) {
        PC22->next = ActK->PC;
        ActK->PC = PC21;
        if (PC12 != NULL) PC12->next = NULL;
     }
  }

  return Ok;
}

void DeleteActionsByCharacter(PredKnowledge *Pd)
{
  PredKnowledge *PC;
  ActKnowledge  *ActK, *ActK1, *ActK2;

  for (ActK = Pd->Act; ActK != NULL; ActK = ActK->next) {
    for (PC = ActK->PC; PC != NULL; PC = PC->next)
      if (IsType(PC->Character, CHARACTER) && CheckTheFact(PC)) break;

    if (PC != NULL) break;
  }

  if (ActK != NULL) {
     for (ActK2 = Pd->Act; ActK2 != NULL; ActK2 = ActK1) {
       ActK1 = ActK2->next;
       if (ActK2 != ActK) FreeActKnowledge(ActK2);
     }

     Pd->Act = ActK;
     ActK->prev = ActK->next = NULL;
     Pd->NumAct = 1;
  }
}

void DeleteActionsByMutex(PredKnowledge *Pd)
{
  PredKnowledge *PC;
  ActKnowledge  *ActK, *ActK1;
  Bool          Found, *Flag;
  int           i;

  Flag = (Bool *) calloc(Pd->NumAct, sizeof(Bool));

  i = 0;
  for (ActK = Pd->Act; ActK != NULL; i++,ActK=ActK->next) {
    for (PC = ActK->PC; PC != NULL; PC = PC->next)
      if (IsType(PC->Character, MUTEX)) {
         Flag[i] = CheckTheFact(PC);
         break;
      }
  }

  Found = FALSE;
  for (i = 0; i < Pd->NumAct; i++) Found = Found || Flag[i];

  if (Found) {
     ActK = Pd->Act;
     for (i = 0; i < Pd->NumAct; i++,ActK=ActK1) {
       ActK1 = ActK->next;
       if (!Flag[i]) DeleteActKnowledge(ActK);
     }
  }

  free(Flag);
}

int DifferentTwoValueList(TokenList *Pt1, TokenList *Pt2)
{
  int Num = 0;

  while (Pt1 != NULL) {
    if (!EqualTwoVLists(&(Pt1->VList), &(Pt2->VList))) Num++;
    Pt1 = Pt1->next;
    Pt2 = Pt2->next;
  }

  return Num;
}

void MergeParaOfPC(PCParaLink *PL)
{
  PCParaLink *Pt1, *Pt2, *Pt3, *Pt4;
  TokenList  *Pt5, *Pt6;

  for (Pt1 = PL; Pt1 != NULL; Pt1 = Pt1->next) {
    Pt3 = Pt1;
    Pt2 = Pt1->next;
    while (Pt2 != NULL) {
      Pt4 = Pt2->next;

      Pt5 = Pt1->Para;
      Pt6 = Pt2->Para;
//PrintTokenList(FALSE, Pt5); fprintf(Output, " F:%d\n", Pt1->Fact);
//PrintTokenList(FALSE, Pt6); fprintf(Output, " F:%d\n", Pt2->Fact);
      if (Pt2->Fact != Pt1->Fact) {
         while (Pt5 != NULL) {
           if (!EqualTwoVLists(&(Pt5->VList), &(Pt6->VList))) break;
           Pt5 = Pt5->next;
           Pt6 = Pt6->next;
         }

         if (Pt5 == NULL) {
             FreeTokenList(Pt2->Para); free(Pt2);
             Pt3->next = Pt4;
         }
      }
      else if (DifferentTwoValueList(Pt5, Pt6) != 1) Pt3 = Pt2;
      else {
             while (Pt5 != NULL) {
               MergeTwoVLists(&(Pt5->VList), &(Pt6->VList));
               Pt5 = Pt5->next;
               Pt6 = Pt6->next;
             }
             FreeTokenList(Pt2->Para); free(Pt2);
             Pt3->next = Pt4;
      }

      Pt2 = Pt4;
    }
  }
}

Bool ValueInValueListOfStaticPC(TypedList *APara, int NumStPC, Bool *Flag, ValueListOfPC *PL)
{
  PCParaLink *PL1;
  TypedList  *Pt1, *Pt2;
  TokenList  *Pt;
  Bool       Found;
  int        i, j;

  Found = FALSE;
  for (i = 0; i < NumStPC; i++) {
    if (PL[i].Status == IGNORE) Found = TRUE;

    for (PL1 = PL[i].List; PL1 != NULL; PL1 = PL1->next) {
      Pt1 = PL[i].PC->Para;
      for (Pt = PL1->Para; Pt != NULL; Pt1++,Pt=Pt->next) {
        j = Pt1->VList.ParaIdx;

        if (IsConstant(j)) continue;

        Pt2 = APara + j;
        if (Pt2->VList.NumValue == 0 ||
            !EqualTwoVLists(&(Pt2->VList), &(Pt->VList))) break;
      }

      if (Pt == NULL) {
         PL[i].Status = DELETE;
         Found = TRUE;
         break;
      }
    }

    if (PL1 != NULL) break;
  }

  return Found;
}

void HandleValueListOfPCs(int NumPC, int NumStPC, Bool *Flag, ValueListOfPC *PL)
{
  PredKnowledge *PC;
  ActKnowledge  *ActK;
  PCParaLink    *PL1, *PL2, *PL3;
  TypedList     *APara, *Pt1, *Pt2;
  TokenList     *Pt;
  int           i, j, NumPara;

  ActK = PL[0].PC->PAct;
  NumPara = NumParaOfAct(ActK->ActNo);
  APara = (TypedList *) calloc(NumPara, sizeof(TypedList));

  for (i = NumStPC; i < NumPC; i++) {
    PC = PL[i].PC;
    PL3 = NULL;
    for (PL1 = PL[i].List; PL1 != NULL; PL1 = PL2) {
      Pt1 = APara;  Pt2 = ActK->Para;
      for (j = 0; j < NumPara; j++,Pt1++,Pt2++)
        CopyOneTypedList(Pt1, Pt2);

//PrintTypedArray("ActName", NumPara, APara); fprintf(Output, "\n");
      Pt1 = PC->Para;
      for (Pt = PL1->Para; Pt != NULL; Pt1++,Pt=Pt->next) {
        j = Pt1->VList.ParaIdx;
        if (!IsConstant(j)) {
           Pt2 = APara + j;
           CopyValueList(&(Pt2->VList), &(Pt->VList));
        }
      }
//PrintTypedArray("ActName", NumPara, APara); fprintf(Output, "\n");

      PL2 = PL1->next;
      if (ValueInValueListOfStaticPC(APara, NumStPC, Flag, PL)) PL3 = PL1;
      else {
             FreeTokenList(PL1->Para); free(PL1);
             if (PL3 == NULL) PL[i].List = PL2;
             else PL3->next = PL2;
      }
    }
  }

  FreeTypedArray(NumPara, APara);

  for (j = 0; j < NumStPC; j++)
    if (PL[j].Status == DELETE) {
       for (PL1 = PL[j].List; PL1 != NULL; PL1 = PL2) {
         PL2 = PL1->next;
         FreeTokenList(PL1->Para);  free(PL1);
       }
       PL[j].List = NULL;
    }
}

Bool HaveNonValue(PredKnowledge *PC, Bool *Para)
{
  int i, j, Num;

  Num = NumParaOfPred(PC->PredNo);
  for (i = 0; i < Num; i++) {
    j = (PC->Para+i)->VList.ParaIdx;
    if (!IsConstant(j) && !Para[j]) break;
  }

  return (i < Num);
}

//EEEEEEEEE
void InstanceActionByValueOfPC(ActKnowledge *ActK, int idx, ValueListOfPC *PL)
{
  PredKnowledge *PC, *PC1, *Parent;
  ActKnowledge  *ActK1;
  PCParaLink    *PL1;
  TypedList     *Para;
  TokenList     *Pt;
  int           Num1, Num2;

  Parent = ActK->Parent;

  for (PL1 = PL[idx].List; PL1 != NULL; PL1 = PL1->next) {
//PrintPredication(12, Parent); fprintf(Output, "\n");
    ActK1 = CopyActKnowledge(ActK, Parent);
    for (PC = ActK1->PC; PC != NULL; PC = PC->next)
      if (PC->Index == idx) break;

    InsertActKnowledge(BEFORE, ActK, ActK1);

    PL1->Used = TRUE;
    PC->Fact = PL1->Fact;
    for (Para=PC->Para,Pt=PL1->Para; Pt != NULL; Para++,Pt=Pt->next) {
      Num1 = Para->VList.NumValue;
      Num2 = Pt->VList.NumValue;
      if (Num1 == 0 || Num1 > Num2) {
         CopyValueList(&(Para->VList), &(Pt->VList));
         PC->NumNonValue--;
      }
    }

//PrintActKnowledge(1, ActK1);  fprintf(Output, "\n");
    ChangeParaOfActionByPC(ActK1, PC);
    for (PC1 = ActK1->PC; PC1 != NULL; PC1 = PC1->next)
      if (PC1->NumNonValue > 0) ChangeOnePCByAction(PC1, ActK1->Para);

    for (PC1 = ActK1->PC; PC1 != NULL; PC1 = PC1->next)
      if (PC1->NumNonValue > 0 && PL[PC1->Index].List != NULL) break;

//PrintActKnowledge(1, ActK1);  fprintf(Output, "\n");
    if (PC1 != NULL) {
       InstanceActionByValueOfPC(ActK1, PC1->Index, PL);
       continue;
    }

    if (!HandlePCsOfNewAction(ActK1)) DeleteActKnowledge(ActK1);
    else {
           ActK1->Index = 10*ActK->Index + idx;
           InstanceEffectOfAction(ActK1); // Instance Private Effect of ActK
           SortPCsOfAction(ActK1);        // and Sort PCs
    }
  }

  DeleteActKnowledge(ActK);
}

void InstantAction(ActKnowledge *ActK)
{
  PredKnowledge *Pd, *PC;
  ValueListOfPC *PL;
  PCParaLink    *PL1, *PL2;
  Bool          NONMainPC, *Flag;
  int           i, j, Num, NAPara, NumStPC;

  Pd = ActK->Parent;
  Num = NumParaOfPred(Pd->PredNo);
  NAPara = NumParaOfAct(ActK->ActNo);
  Flag = (Bool *) calloc(NAPara, sizeof(Bool));
  for (i = 0; i < NAPara; i++)
    Flag[i] = ((ActK->Para+i)->VList.ParaIdx < Num);

  // Check whether the PC is main PC
  NONMainPC = TRUE;
  if (IsType(Pd->Character, MAINPC)) {
     NONMainPC = FALSE;
     for (PC = ActK->PC; PC != NULL; PC = PC->next)
       if (IsType(PC->Character, MAINPC)) break;

     if (PC != NULL) {
        Num = NumParaOfPred(PC->PredNo);
        for (i = 0; i < Num; i++) {
          j = (PC->Para+i)->VList.ParaIdx;
          if (!IsConstant(j)) Flag[j] = TRUE;
        }
     }
  }

  Num = 0;
  for (PC = ActK->PC; PC != NULL; PC = PC->next) Num++;

  PL = (ValueListOfPC *) calloc(Num, sizeof(ValueListOfPC));

//PrintActKnowledge(1, ActK);  fprintf(Output, "\n");
//if (Typing) ActK = InstantActionForTyping(ActK);
  for (i=0,PC=ActK->PC; PC != NULL; i++,PC=PC->next) {
    PC->Index = i;
    PL[i].PC = PC;
    if (!IsEqual(PC->PredNo) && PC->NumNonValue > 0) {
       if (NONMainPC || IsType(PC->Character, MAINPC)
           || IsClass(PC->PredNo, STATIC)
           || HaveNonValue(PC, Flag))
          PL[i].List = GetParaWithFactNFFact(FALSE, TNCA, PC);
       else PL[i].Status = IGNORE;
    }
  }

//for (i = 0; i < Num; i++) PrintValueListOfPC(i, PL);

  NumStPC = 0;
  for (i = 0; i < Num; i++,NumStPC++)
    if (!IsClass(PL[i].PC->PredNo, STATIC)) break;

  if (NumStPC > 0) HandleValueListOfPCs(Num, NumStPC, Flag, PL);

  for (i = 0; i < Num; i++) {
    if (PL[i].List != NULL) MergeParaOfPC(PL[i].List);
//PrintValueListOfPC(i, PL);
  }

  for (i = 0; i < Num; i++)
    if (PL[i].List != NULL) break;

//PrintPredication(12, Pd); fprintf(Output, "\n");
  if (i < Num) InstanceActionByValueOfPC(ActK, i, PL);
//PrintPredication(12, Pd); fprintf(Output, "\n");

  for (i = 0; i < Num; i++)
    for (PL1 = PL[i].List; PL1 != NULL; PL1 = PL2) {
      PL2 = PL1->next;
      FreeTokenList(PL1->Para);  free(PL1);
    }

  free(Flag);  free(PL);
}

void SortActionByParameter(PredKnowledge *Pd)
{
  ActKnowledge *ActK, *ActK1, *ActK2, *ActK3, *ActK4;
  TypedList    *Para;
  int           i, Num;

  ActK1 = NULL;
  ActK = Pd->Act;
  while (ActK != NULL) {
    ActK2 = ActK->next;

    Num = NumParaOfAct(ActK->ActNo);
    Para = ActK->Para;
    for (i = 0; i < Num; i++,Para++)
      if (Para->VList.NumValue == 0) break;

    if (i >= Num) {
       ActK3 = ActK->prev;
       ActK4 = ActK->next;

       if (ActK3 == NULL) Pd->Act = ActK4;
       else ActK3->next = ActK4;

       if (ActK4 != NULL) ActK4->prev = ActK3;

       if (ActK1 == NULL) ActK4 = Pd->Act;
       else ActK4 = ActK1->next;

       ActK->next = ActK4;    ActK->prev = ActK1;

       if (ActK1 == NULL) Pd->Act = ActK;
       else ActK1->next = ActK;

       if (ActK4 != NULL) ActK4->prev = ActK;

       ActK1 = ActK;
    }

    ActK = ActK2;
  }
}

/*void CopyListOfCPC(PredKnowledge *Pd, PredKnowledge *Pred)
{
  PredKnowledge *PC, *PC1, *PC2;
  TypedList     *Para, *Para1;
  int            i, Num, Idx, Num1;

  Pd->NumEP = Pred->NumEP;

  Num = NumParaOfPred(Pd->PredNo);
  Pd->Para = (TypedList *) realloc(Pd->Para, (Num+Pd->NumEP)*sizeof(TypedList));

  Para = Pd->Para + Num;
  for (i = 0; i < Pd->NumEP; i++,Para++) Para->VList.ParaIdx = NOFOUND;

  Pd->CPC = NULL;
  for (PC = Pred->CPC; PC != NULL; PC = PC->next) {
    PC1 = CopyOnePC(PC);

    PC1->Parent = Pd;
    PC1->Level = Pd->Level + 2;

    Num1 = NumParaOfPred(PC1->PredNo);
    Para = PC1->Para;
    for (i = 0; i < Num1; i++,Para++) {
      Idx = Para->VList.ParaIdx;

      if (IsConstant(Idx)) continue;

      if (Idx >= Num) {
         Para1 = Pd->Para + Idx;
         Para1->VList.ParaIdx = Para->VList.ParaIdx;
         strcpy(Para1->VList.Name, Para->VList.Name);
         Para1->Type = CopyListOfType(Para->Type);
      }
    }

    if (Pd->CPC == NULL) Pd->CPC = PC1;
    else PC2->next = PC1;

    PC2 = PC1;
  }
}*/

void AddOneValueOfPara(TypedList *Para1, TypedList *Para2)
{
//if (Para2->VList.NumValue == 0)
// No finish
}

void ModifyInfoOfActionTree(PredKnowledge *Pd)
{
  ActKnowledge *ActK;
  TypedList    *Para, *APara;
  int           i, idx, Num, Num1;

//PrintPredication(12, Pd); fprintf(Output, "\n");
  Num = NumParaOfPred(Pd->PredNo);
  Para = (TypedList *) calloc(Num, sizeof(TypedList));

  for (ActK = Pd->Act; ActK != NULL; ActK = ActK->next) {
    Num1 = NumParaOfAct(ActK->ActNo);
    APara = ActK->Para;
    for (i = 0; i < Num1; i++,APara++) {
      idx = APara->VList.ParaIdx;
      if (!IsConstant(idx)) AddOneValueOfPara(Para+idx, APara);
    }
  }
//PrintPredication(12, Pd); fprintf(Output, "\n");
}

#ifdef WHEN_CLAUSE
Bool PredDeletedByEffectOfWhen(PredKnowledge *Pd, PENode *PE)
{
  TypedList *Para;
  TokenList *Pt1;
  PENode    *PE1;
  VList     *Pt;
  int        idx;

  for (PE1 = PE; PE1 != NULL; PE1 = PE1->next) {
    if (Pd->Type == PE1->Type ||
        Pd->PredNo != PE->Pred->VList.ParaIdx) continue;

    Para = Pd->Para;
    for (Pt1 = PE1->Pred->next; Pt1 != NULL; Para++,Pt1=Pt1->next) {
      idx = Para->VList.List->Idx;
      for (Pt = Pt1->VList.List; Pt != NULL; Pt = Pt->next)
        if (Pt->Idx == idx) break;

      if (Pt == NULL) break;
    }

    if (Pt1 == NULL) break;
  }

  return (PE1 != NULL);
}

void InsertNotConditionOfWhenClause(ActKnowledge *ActK, PENode *PE)
{
  PredKnowledge *PC;
  TypedList     *Para;
  TokenList     *Pt;
  int            Num;

  PC = (PredKnowledge *) calloc(1, sizeof(PredKnowledge));

  PC->Fact = TRUE;
  PC->Type = (PE->Type==ATOM ? NOT : ATOM);

  PC->Parent = ActK->Parent;
  PC->Level = ActK->Parent->Level + 2;

  Pt = PE->Pred;
  PC->PredNo = Pt->VList.ParaIdx;

  Num = NumParaOfPred(Pt->VList.ParaIdx);

  if (Num == 0) return;

  PC->Para = Para = (TypedList *) calloc(Num, sizeof(TypedList));
  for (Pt = Pt->next; Pt != NULL; Para++,Pt=Pt->next) {
    Para->VList.ParaIdx = Pt->VList.ParaIdx;
    CopyValueList(&(Para->VList), &(Pt->VList));
  }

  PC->next = ActK->PC;
  ActK->PC = PC;
}

void DeleteByWhenClause(PredKnowledge *Pd)
{
  PredKnowledge *Pred;
  ActKnowledge  *ActK;
  PENode        *PE, *PE1;
  int i;

  for (i = 0; i < NumTarget; i++) {
    Pred = Target[i].Pred;
    ActK = Pd->Act;
    PE1 = NULL;
    for (PE = ActK->CondEffect; PE != NULL; PE1=PE,PE=PE->next)
      if (PredDeletedByEffectOfWhen(Pred, PE->Effect)) {
         if (PE1 == NULL) ActK->CondEffect = PE->next;
         else PE1->next = PE->next;

         InsertNotConditionOfWhenClause(ActK, PE->sons);

         FreeTokenList(PE->sons->Pred);  free(PE->sons);
         FreeEffectList(PE->Effect);

         free(PE);
         break;
      }
  }
}
#endif

void GenerateKnowledgeTreeByDFS(int Height, PredKnowledge *Pd)
{
  PredKnowledge *PC;
  ActKnowledge  *ActK, *ActK1, *ActK2;
  TypedList     *Pt1, *Pt2;
  PKTree        *Pk;
  Bool           UComplete;
  int            i, Idx, HAct, Acts, Num;

  Pd->Fact = TRUE;
  Pd->Act = NULL;
  Pd->CPC = NULL;  Pd->CEffect = NULL;

//PrintPredication(12, Pd); fprintf(Output, "\n");
  Idx = 1;  ActK1 = NULL;
  Pk = (Pd->Type==ATOM ? PK : nPK) + Pd->PredNo;
  for (Pk = Pk->next; Pk != NULL; Pk = Pk->next) {
    if (!CheckPredKnowledgeTree(Pk, Pd)) continue;
//PrintPredication(12, Pk->Pred); fprintf(Output, "\n");

    PC = Pk->Pred;
    Pd->Character = (Idx==1 ? PC->Character : NONE);

    if (Pd->NumEP < PC->NumEP) {
       Pd->NumEP = PC->NumEP;
       Num = NumParaOfPred(Pd->PredNo);

       Pd->Para = (TypedList *) realloc(Pd->Para, (Num+PC->NumEP)*sizeof(TypedList));

       Pt1 = Pd->Para + Num;
       Pt2 = PC->Para + Num;
       for (i = 0; i < PC->NumEP; i++,Pt1++,Pt2++) {
         Pt1->VList.ParaIdx = Num + i;
         strcpy(Pt1->VList.Name, Pt2->VList.Name);
         Pt1->Type = CopyListOfType(Pt2->Type);

         Pt1->VList.List = NULL;
         CopyValueList(&(Pt1->VList), &(Pt2->VList));
       }
    }

    //CopyListOfCPC(Pd, PC);
    CopyListOfCEffect(Pd, PC);

    for (ActK = PC->Act; ActK != NULL; ActK = ActK->next) {
      ActK2 = CopyActKnowledge(ActK, Pd);

//PrintActKnowledge(Pd->Level, ActK2);  fprintf(Output, "\n");
      ChangeParaOfActionByPred(ActK2, Pd);
#ifdef CHANGENAME
      ChangeNameParaOfAction(ActK2, Pd);
#endif

//PrintActKnowledge(Pd->Level, ActK2);  fprintf(Output, "\n");
      for (PC = ActK2->PC; PC != NULL; PC = PC->next)
        ChangeOnePCByAction(PC, ActK2->Para);

//PrintActKnowledge(1, ActK2);  fprintf(Output, "\n");
      if (!HandlePCsOfNewAction(ActK2)) FreeActKnowledge(ActK2);
      else {
             SortPCsOfAction(ActK2);
             InstanceEffectOfAction(ActK2);
//PrintActKnowledge(Pd->Level, ActK2);  fprintf(Output, "\n");

             ActK2->Index = Idx++;

             if (ActK1 != NULL) InsertActKnowledge(AFTER, ActK1, ActK2);
             else { Pd->Act = ActK2; Pd->NumAct++; }

             ActK1 = ActK2;
      }
    }
  }
//PrintPredication(12, Pd); fprintf(Output, "\n");

  if (Pd->Act == NULL) return;

  // HANDLE_CHARACTER
  if (IsType(Pd->Character, CHARACTER) && Pd->NumAct > 1)
     DeleteActionsByCharacter(Pd);

  // HANDLE_MUTEX
  if (IsType(Pd->Character, MUTEX)) DeleteActionsByMutex(Pd);

//PrintPredication(12, Pd); fprintf(Output, "\n");
  for (ActK = Pd->Act; ActK != NULL; ActK = ActK1) {
    ActK1 = ActK->next;
    if (ActK->PC != NULL) InstantAction(ActK);
  }

#ifdef WHEN_CLAUSE
  DeleteByWhenClause(Pd);
#endif

//PrintPredication(12, Pd); fprintf(Output, "\n");
//ModifyInfoOfActionTree(Pd);

  SortActionByParameter(Pd);

  ActK = Pd->PAct;
  if (ActK != NULL) CheckAllPCsOfAction(ActK);

  HAct = Height - 1;
  for (ActK = Pd->Act; ActK != NULL; ActK = ActK2) {
    ActK2 = ActK->next;

    ActK1 = ActK->prev;
    if (!ExpandOneActKnowledge(HAct, ActK))
       DeleteActKnowledge(ActK);
    else if (!ActK->UComplete && HAct>ActK->Height) HAct = ActK->Height;
  }
//PrintPredication(12, Pd); fprintf(Output, "\n");

  UComplete = TRUE;
  HAct = Acts = MAX_HEIGHT;
  for (ActK = Pd->Act; ActK != NULL; ActK = ActK->next) {
    if (ActK->UComplete) continue;

    if (HAct > ActK->Height) HAct = ActK->Height;
    if (Acts > ActK->Acts) Acts = ActK->Acts;

    UComplete = UComplete && ActK->UComplete;
  }

  if (Pd->Act != NULL) {
     Pd->UComplete = UComplete;
     Pd->Height = HAct + 1;
     Pd->Acts = Acts + 1;
  }

//PrintPredication(12, Pd); fprintf(Output, "\n");
  if (ModifyParaOfPredByActions(Pd)==ERROR || ExistPCLoop(Pd))
     FreeActionsOfPred(Pd);
}

Bool ModifyKnowledgeTree(int Height, PredKnowledge *PC)
{
  PredKnowledge *PC1, *Parent;
  ActKnowledge  *ActK1, *ActK2, *ActK3;
  Bool           Ok, Ok1, UComplete;
  int            HAct, HPc, Acts1, Acts2;

//PrintPredication(12, PC); fprintf(Output, "\n");
  PC->Acts = PC->Height = 0;

  Ok = (FindAndInstantByFacts(PC) == 1);
  if (PC->Type == NOT) Ok = !Ok;
  if (Ok){//} && !PC->Expand) { // Error
     FreeActionsOfPred(PC);
     PC->Fact = TRUE;
     return TRUE;
  }

  Parent = PC->Parent;
  if (Parent!=NULL && FindOneNoConfirmFact(PC, NULL)) {
     FreeActionsOfPred(PC);
     PC->Fact = FALSE;
     return TRUE;
  }

  HPc = PC->Height;
  if ((0<=HPc && HPc<=2) || (PC->UComplete && PC->Act==NULL)) {
     FreeActionsOfPred(PC);
     GenerateKnowledgeTreeByDFS(Height, PC);
     return (PC->Act != NULL);
  }

  ActK1 = PC->Act;
  if (ActK1 == NULL) return FALSE;

  Ok = FALSE;
  HAct = Acts2 = MAX_HEIGHT;
  for ( ; ActK1 != NULL; ActK1 = ActK2) {
    ActK2 = ActK1->next;

    ActK3 = ActK1->prev;
//  if (ActK3!=NULL && (int)ActK3->Index1/10==ActK1->Index1)
//     continue;

    HPc = Acts1 = 0;
    Ok1 = UComplete = TRUE;
    for (PC1=ActK1->PC; Ok1 && PC1!=NULL; PC1=PC1->next) {
      Ok1 = ModifyKnowledgeTree(Height-1, PC1);
      if (HPc < PC1->Height) HPc = PC1->Height;
      Acts1 += PC1->Acts;
      UComplete = UComplete && PC1->UComplete;
    }

    if (!Ok1) DeleteActKnowledge(ActK1);
    else {
           Ok = TRUE;
           ActK1->Height = HPc;
           ActK1->Acts = Acts1;
           ActK1->UComplete = UComplete;
           if (HPc < HAct) HAct = HPc;
           if (Acts1 < Acts2) Acts2 = Acts1;
    }
  }

  if (PC->Act != NULL) {
     PC->Height = HAct + 1;
     PC->Acts = Acts2 + 1;
  }

  ModifyParaOfPredByActions(PC);
  return Ok;
}
#endif
